import inquirer, { DistinctQuestion, Question } from 'inquirer';
import path from 'path';
import { buildCocos, buildRpk } from './BuildCocos';
import { compressOrigin } from './CompressImg';
import { copyFiles, getFiles, runCmd } from './Utils';
import { promises as fs } from 'fs';
import chalk from 'chalk';
import { versionPack } from './VersionPack';
import { readJSON, readJsonSync } from 'fs-extra';
import { upload } from './upload';
import { ServerConfig, VersionConfig } from './types';
import { updateVersion } from './updateVersion';
import { AsyncGetterFunction } from 'inquirer/dist/commonjs/types';

const PROJECT_ROOT = path.resolve(__dirname, '../..');

const normalProject = ['googleAd', 'wechatgame', 'huawei-quick-game', 'oppo-mini-game', "web-mobile"]

interface TemplateOptions {
    projectName: string;
    projectType: typeof normalProject[number];
    projectDir: string;
    action: 'build' | 'buildAndUp' | 'compressImg' | "rpk" | "action";
    compressImg: 'yes' | 'no'
    rpkMod: 'debug' | 'release'
    singleAction: "upload" | "compressImg" | "versionPack" | "uploadDir";
    when?: boolean | AsyncGetterFunction<boolean, TemplateOptions>;
}

type SettingsType = {
    [projectName: string]: {
        exeDir: string,
        projectDir: string,
        gitStorage: string,
        buildConfDir: string
        uploadCfg: ServerConfig
    }
}

function action(): DistinctQuestion<TemplateOptions>[] {
    return [
        {
            type: 'list',
            name: 'projectType',
            message: '选择项目',
            choices: normalProject
        },
        {
            type: 'list',
            name: 'singleAction',
            message: '操作',
            choices: ['upload', 'compressImg', 'versionPack']
        }
    ]
}

function build(): DistinctQuestion<TemplateOptions>[] {
    return [
        {
            type: 'list',
            name: 'projectType',
            message: '选择项目',
            choices: normalProject
        },
        {
            type: 'list',
            name: 'compressImg',
            message: '是否压图片',
            choices: ['yes', 'no'],
        }
    ]
}

function rpk(): DistinctQuestion<TemplateOptions>[] {
    return [
        {
            type: 'list',
            name: 'projectType',
            message: '选择项目',
            choices: ['huawei-quick-game', 'oppo-mini-game']
        },
        {
            type: 'list',
            name: 'rpkMod',
            message: '调试或发布',
            choices: ['release', 'debug'],
        }
    ]
}

export default async (): Promise<void> => {
    let settings = JSON.parse(await fs.readFile(path.join(PROJECT_ROOT, 'settings.json'), 'utf-8')) as SettingsType
    try {
        let answers = await inquirer.prompt<TemplateOptions>([
            {
                type: 'list',
                name: 'projectName',
                message: '项目名称',
                choices: Object.keys(settings),
                when: () => Object.keys(settings).length > 1 // 条件显示
            },
            {
                type: 'list',
                name: 'action',
                message: '流程选择',
                choices: ['build', 'buildAndUp', 'action', "rpk"] // 三个主要功能
            }
        ])

        if (answers.action === 'build' || answers.action === 'buildAndUp') {
            let data = await inquirer.prompt<TemplateOptions>(build())
            answers = { ...answers, ...data }
        }
        else if (answers.action === 'rpk') {
            let data = await inquirer.prompt<TemplateOptions>(rpk())
            answers = { ...answers, ...data }
        } if (answers.action === 'action') {
            let data = await inquirer.prompt<TemplateOptions>(action())
            answers = { ...answers, ...data }
        }
        console.log(answers);

        const defaultProjectName = answers.projectName || Object.keys(settings)[0]

        const { exeDir, projectDir, buildConfDir: _buildConfDir, gitStorage, uploadCfg } = settings[defaultProjectName];

        const buildConfDir = `${_buildConfDir}${answers.projectType}.json`
        const buildOutputDir = path.join(projectDir, "build", answers.projectType)

        /**处理函数map */
        const actionMap = {
            'build': async () => {
                await buildCocos(exeDir, projectDir, buildConfDir, answers.projectType)
            },
            "compressImg": async () => {
                await compressOrigin(buildOutputDir)
            },
            "rpk": async () => {
                await buildRpk(answers.projectType, buildOutputDir, answers.rpkMod === 'release')
            },
            "copyFiles": async () => {
                await copyFiles(buildOutputDir, path.join(gitStorage, "game"))
            },
            "versionPack": async () => {
                runCmd(`git pull origin master && git add . && git commit -m "update ${answers.projectType}"`, gitStorage)
                await versionPack(gitStorage)
                runCmd(`git commit -m "versionPack end ${answers.projectType}"`, gitStorage)
                runCmd(`git push origin master`, gitStorage)

            },
            "upload": async () => {
                let uploadFiles = readJsonSync(path.join(gitStorage, `upload.json`))
                uploadCfg.localPath = path.join(gitStorage, `upRes`)
                await upload(uploadCfg, uploadFiles)
                let cfg = await readJSON(path.join(gitStorage, `config.json`)) as VersionConfig
                await updateVersion(cfg.ver - 1, cfg.lastCommit)
            },
            "uploadDir": async () => {
                let uploadFiles = await getFiles(path.join(gitStorage, `upload.json`))
                await upload(uploadCfg, uploadFiles)
            }
        }

        let pipeline: (keyof typeof actionMap)[] = []
        switch (answers.action) {
            case 'build':
                pipeline.push('build')
                if (answers.compressImg === 'yes') {
                    pipeline.push('compressImg')
                }
                break;
            case 'buildAndUp':
                pipeline.push('build')
                if (answers.compressImg === 'yes') {
                    pipeline.push('compressImg')
                }
                pipeline.push('copyFiles')
                pipeline.push('versionPack')
                pipeline.push("upload")
                break;
            case 'rpk':
                pipeline.push('rpk')
            case 'action':
                if (answers.singleAction === 'upload')
                    pipeline.push('upload')
                else if (answers.singleAction === 'compressImg')
                    pipeline.push('compressImg')
                else if (answers.singleAction === 'versionPack') {
                    pipeline.push('copyFiles')
                    pipeline.push('versionPack')
                }
                else if (answers.singleAction === 'uploadDir') {
                    pipeline.push('uploadDir')
                }

        }
        console.log(chalk.yellow(`${answers.projectType}----${pipeline.join('->')}`));
        for (const iterator of pipeline) {
            await actionMap[iterator]()
        }

    } catch (error: any) {
        console.log(error.message);
    }
};
